Dữ liệu được lấy từ 1 cửa hàng thực tế. Tuy nhiên để đảm bảo việc bảo mật dữ liệu 1 số thông tin đã bị mã hóa và thay đổi
import pyodbc
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go
import plotly.offline as plot
import ipywidgets as widgets
from jupyter_dash import JupyterDash
from dash import Dash, dcc, html, Input, Output
import warnings
warnings.filterwarnings("ignore")
Dữ liệu được lấy từ web bán hàng, có thể lấy dữ liệu theo ngày hoặc theo tháng. Dữ liệu được lấy xuống là 1 data frame gồm rất nhiều trường thông tin. Chúng ta sẽ xử lý để tách làm 3 bảng và đẩy vào SQL server để lưu trữ và tính toán
SVNAME = 'DESKTOP-V57CC5Q\HOCSQL'
DBNAME = 'QLBHTKL'
username = ''
password = ''
conn = pyodbc.connect('DRIVER={SQL Server};SERVER='+SVNAME+';DATABASE='+DBNAME+';UID='+username+';PWD='+ password)
cursor = conn.cursor()
input_file_path = "D:/courses.funix/CV/Data/"
output_file_path = "D:/courses.funix/CV/"
excel_file_list = os.listdir(input_file_path)
df = pd.DataFrame()
for excel_files in excel_file_list:
if excel_files.endswith(".xlsx"):
df1 = pd.read_excel(input_file_path+excel_files)
df = df.append(df1)
df.to_excel(output_file_path+"Data_file.xlsx")
df = pd.read_excel('Data_file.xlsx')
df.head(5)
| STT | MÃ CN | CHI NHÁNH | NGÀY HĐ | SỐ HĐ | MÃ KHÁCH 2 | TÊN KHÁCH | MÃ HÀNG | TÊN HÀNG | GIỚI TÍNH | ... | THÀNH TIỀN BÁN | THÀNH TIỀN NTL | MÔ TẢ | HẠNG KHÁCH | CHƯƠNG TRÌNH KHUYẾN MẠI | SubClass1 | THUỘC TÍNH 1 | NĂM SX | MÃ HÀNG1 | NHÂN VIÊN | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000175 | 1160637 | Trần Thị Hằng | I7JCK601F-015 | Áo khoác lông vũ Nam 3 lớp cổ 5cm dáng ngắn I7... | Nam | ... | 0.0 | 387000.0 | NaN | AppMember | NaN | cổ 5cm | 3 lớp | Đông 2019 | I7JCK601F | NaN |
| 1 | 2 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000176 | 907256 | Chị Oanh | I9COA502H-005 | Áo khoác Nữ dáng dài I9COA502H | Nữ | ... | 0.0 | 474000.0 | NaN | AppMember | NaN | có mũ | 2 lớp mỏng | Đông 2020 | I9COA502H | NaN |
| 2 | 3 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000177 | 163424 | Nguyễn Thị Hà | I7SWT601F-001 | Áo len Nam cổ tròn I7SWT601F | Nam | ... | 0.0 | 147000.0 | NaN | AppMember | NaN | cổ tròn | Len | Đông 2019 | I7SWT601F | NaN |
| 3 | 4 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000178 | 1834386 | Nguyễn Minh Nguyệt | M9ACP500H-002 | Quần Leggings lửng Nữ M9ACP500H | Nữ | ... | 0.0 | 45000.0 | NaN | AppMember | NaN | NaN | NaN | Đông 2020 | M9ACP500H | NaN |
| 4 | 5 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000179 | 1984934 | Chị Hà | C9SML008D-002 | Quần Leggings Nữ C9SML-008D | Nữ | ... | 0.0 | 87000.0 | NaN | AppMember | NaN | NaN | NaN | Đông 2018 | C9SML-008D | NaN |
5 rows × 33 columns
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 115050 entries, 0 to 115049 Data columns (total 33 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 STT 115050 non-null int64 1 MÃ CN 115050 non-null int64 2 CHI NHÁNH 115050 non-null object 3 NGÀY HĐ 115050 non-null datetime64[ns] 4 SỐ HĐ 115050 non-null object 5 MÃ KHÁCH 2 115050 non-null int64 6 TÊN KHÁCH 115050 non-null object 7 MÃ HÀNG 115050 non-null object 8 TÊN HÀNG 115050 non-null object 9 GIỚI TÍNH 76296 non-null object 10 NHÓM HÀNG 115050 non-null object 11 THƯƠNG HIỆU 109602 non-null object 12 KÍCH CỠ 93469 non-null object 13 MÀU SẮC 82452 non-null object 14 ĐƠN VỊ 115040 non-null object 15 DÒNG HÀNG 115006 non-null object 16 KẾT CẤU 114977 non-null object 17 BỘ SƯU TẬP 81575 non-null object 18 SL BÁN 115050 non-null int64 19 SL TRẢ LẠI 115050 non-null int64 20 GIÁ 115050 non-null int64 21 GIẢM GIÁ 115050 non-null float64 22 G.TRÊN HĐ 115050 non-null float64 23 THÀNH TIỀN BÁN 115050 non-null float64 24 THÀNH TIỀN NTL 115050 non-null float64 25 MÔ TẢ 23255 non-null object 26 HẠNG KHÁCH 114445 non-null object 27 CHƯƠNG TRÌNH KHUYẾN MẠI 69094 non-null object 28 SubClass1 46658 non-null object 29 THUỘC TÍNH 1 47907 non-null object 30 NĂM SX 80109 non-null object 31 MÃ HÀNG1 114960 non-null object 32 NHÂN VIÊN 5283 non-null object dtypes: datetime64[ns](1), float64(4), int64(6), object(22) memory usage: 29.0+ MB
columns_khachhang = ['MÃ KHÁCH 2','TÊN KHÁCH']
columns_hanghoa = ['MÃ HÀNG','TÊN HÀNG','GIỚI TÍNH','NHÓM HÀNG','THƯƠNG HIỆU','KÍCH CỠ','MÀU SẮC','ĐƠN VỊ','DÒNG HÀNG','KẾT CẤU','BỘ SƯU TẬP']
columns_hoadon = ['MÃ CN','CHI NHÁNH','NGÀY HĐ','SỐ HĐ','MÃ KHÁCH 2','MÃ HÀNG','SL BÁN','SL TRẢ LẠI','GIÁ','GIẢM GIÁ','G.TRÊN HĐ','THÀNH TIỀN BÁN','THÀNH TIỀN NTL','MÔ TẢ','HẠNG KHÁCH','CHƯƠNG TRÌNH KHUYẾN MẠI','SubClass1','THUỘC TÍNH 1','NĂM SX','MÃ HÀNG1','NHÂN VIÊN']
df_khachhang = df[columns_khachhang].drop_duplicates()
df_khachhang
| MÃ KHÁCH 2 | TÊN KHÁCH | |
|---|---|---|
| 0 | 1160637 | Trần Thị Hằng |
| 1 | 907256 | Chị Oanh |
| 2 | 163424 | Nguyễn Thị Hà |
| 3 | 1834386 | Nguyễn Minh Nguyệt |
| 4 | 1984934 | Chị Hà |
| ... | ... | ... |
| 114986 | 2497284 | Chị Hiền |
| 114989 | 2497294 | Mr Trung |
| 114996 | 2497332 | Ms Liên |
| 115005 | 2497497 | C,Quỳnh |
| 115018 | 2497637 | Ms Hương |
11704 rows × 2 columns
df_hanghoa = df[columns_hanghoa].drop_duplicates()
df_hoadon = df[columns_hoadon]
records_khachhang = df_khachhang.values.tolist()
cursor.execute('''
DROP TABLE IF EXISTS khachhang
CREATE TABLE khachhang (
[MÃ KHÁCH 2] int primary key,
[TÊN KHÁCH] nvarchar(50))
''')
conn.commit()
sql_insert_khachhang = '''
INSERT INTO khachhang
VALUES (?, ?)
'''
cursor.executemany(sql_insert_khachhang, records_khachhang)
cursor.commit();
sql_query = """
SELECT TOP 10 *
FROM khachhang
"""
df_check = pd.read_sql(sql_query, conn)
df_check
| MÃ KHÁCH 2 | TÊN KHÁCH | |
|---|---|---|
| 0 | 125517 | Hoàng Văn Tùng |
| 1 | 126268 | Nguyễn THu huyền |
| 2 | 126363 | Nguyên Thị Nga |
| 3 | 126405 | Cô Nhung |
| 4 | 126568 | Đỗ Thị Tiến Dung |
| 5 | 126781 | Phạm Nhật Lệ |
| 6 | 127020 | Chị Lê Diệu Linh |
| 7 | 127365 | 05 |
| 8 | 127463 | Nv Đỗ Thị Thu Trang |
| 9 | 128042 | Phạm Thị Thu Nga |
records_hanghoa = df_hanghoa.fillna(value=0).values.tolist()
cursor.execute('''
DROP TABLE IF EXISTS hanghoa
CREATE TABLE hanghoa (
[MÃ HÀNG] nvarchar(50) primary key,
[TÊN HÀNG] nvarchar(100),
[GIỚI TÍNH] nvarchar(20),
[NHÓM HÀNG] nvarchar(100),
[THƯƠNG HIỆU] nvarchar(100),
[KÍCH CỠ] nvarchar(50),
[MÀU SẮC] nvarchar(50),
[ĐƠN VỊ] nvarchar(20),
[DÒNG HÀNG] nvarchar(100),
[KẾT CẤU] nvarchar(100),
[BỘ SƯU TẬP] nvarchar(100))
''')
conn.commit()
sql_insert_hanghoa = '''
INSERT INTO hanghoa
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
'''
cursor.executemany(sql_insert_hanghoa, records_hanghoa)
cursor.commit();
sql_query = """
SELECT TOP 10 *
FROM hanghoa
"""
df_check = pd.read_sql(sql_query, conn)
df_check
| MÃ HÀNG | TÊN HÀNG | GIỚI TÍNH | NHÓM HÀNG | THƯƠNG HIỆU | KÍCH CỠ | MÀU SẮC | ĐƠN VỊ | DÒNG HÀNG | KẾT CẤU | BỘ SƯU TẬP | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2733217190301 | Bộ Jumpsuits Bé trai ngắn tay BLA 27332171903 ... | Bé trai | Thời trang NOW | BALABALA | Size 73 | Vàng | Bộ | Bộ | Bộ Jumpsuits | Xuân Hè |
| 1 | 3588981242178-1222 | Nước hoa TOKYOLIFE OCEAN EDP 20ml | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 20ml | 0 | Chai | Nước hoa | Nước hoa | Bốn mùa |
| 2 | 3588981242185-1124 | Nước hoa TOKYOLIFE NIGHT SKY EDP | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 24ml | 0 | Chai | Nước hoa | Nước hoa | Thu đông 2021 |
| 3 | 3588981242185-1222 | Nước hoa TOKYOLIFE NIGHT SKY EDP 20ml | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 20ml | 0 | Chai | Nước hoa | Nước hoa | Bốn mùa |
| 4 | 3588981242192-1124 | Nước hoa TOKYOLIFE UNIVERSE EDP | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 24ml | 0 | Chai | Nước hoa | Nước hoa | Thu đông 2021 |
| 5 | 3588981242192-1222 | Nước hoa TOKYOLIFE UNIVERSE EDP 20ml | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 20ml | 0 | Chai | Nước hoa | Nước hoa | Bốn mùa |
| 6 | 3588981242208-1124 | Nước hoa TOKYOLIFE EARTH EDP | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 24ml | 0 | Chai | Nước hoa | Nước hoa | Thu đông 2021 |
| 7 | 3588981242208-1222 | Nước hoa TOKYOLIFE EARTH EDP 20ml | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 20ml | 0 | Chai | Nước hoa | Nước hoa | Bốn mùa |
| 8 | 3588981242215-1124 | Nước hoa TOKYOLIFE MOUNTAIN EDP | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 24ml | 0 | Chai | Nước hoa | Nước hoa | Thu đông 2021 |
| 9 | 3588981242215-1222 | Nước hoa TOKYOLIFE MOUNTAIN EDP 20ml | Nam | Hàng tiêu dùng nhanh | TOKYOLIFE | 20ml | 0 | Chai | Nước hoa | Nước hoa | Bốn mùa |
records_hoadon = df_hoadon.fillna(value=0).values.tolist()
df_hoadon.columns
Index(['MÃ CN', 'CHI NHÁNH', 'NGÀY HĐ', 'SỐ HĐ', 'MÃ KHÁCH 2', 'MÃ HÀNG',
'SL BÁN', 'SL TRẢ LẠI', 'GIÁ', 'GIẢM GIÁ', 'G.TRÊN HĐ',
'THÀNH TIỀN BÁN', 'THÀNH TIỀN NTL', 'MÔ TẢ', 'HẠNG KHÁCH',
'CHƯƠNG TRÌNH KHUYẾN MẠI', 'SubClass1', 'THUỘC TÍNH 1', 'NĂM SX',
'MÃ HÀNG1', 'NHÂN VIÊN'],
dtype='object')
cursor.execute('''
DROP TABLE IF EXISTS hoadon
CREATE TABLE hoadon (
[STT_ID] INT IDENTITY(1,1) PRIMARY KEY,
[MÃ CN] nvarchar(10),
[CHI NHÁNH] nvarchar(100),
[NGÀY HĐ] datetime,
[SỐ HĐ] nvarchar(50),
[MÃ KHÁCH 2] int FOREIGN KEY REFERENCES khachhang([MÃ KHÁCH 2]),
[MÃ HÀNG] nvarchar(50) FOREIGN KEY REFERENCES hanghoa([MÃ HÀNG]),
[SL BÁN] int,
[SL TRẢ LẠI] int,
[GIÁ] int,
[GIẢM GIÁ] nvarchar(100),
[G.TRÊN HĐ] nvarchar(100),
[THÀNH TIỀN BÁN] float,
[THÀNH TIỀN NTL] float,
[MÔ TẢ] nvarchar(100),
[HẠNG KHÁCH] nvarchar(100),
[CHƯƠNG TRÌNH KHUYẾN MẠI] nvarchar(100),
[SubClass1] nvarchar(100),
[THUỘC TÍNH 1] nvarchar(100),
[NĂM SX] nvarchar(100),
[MÃ HÀNG1] nvarchar(100),
[NHÂN VIÊN] nvarchar(50))
''')
conn.commit()
sql_insert_hoadon = '''
INSERT INTO hoadon
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
'''
cursor.executemany(sql_insert_hoadon, records_hoadon)
cursor.commit();
sql_query = """
SELECT TOP 10 *
FROM hoadon
"""
df_check = pd.read_sql(sql_query, conn)
df_check
| STT_ID | MÃ CN | CHI NHÁNH | NGÀY HĐ | SỐ HĐ | MÃ KHÁCH 2 | MÃ HÀNG | SL BÁN | SL TRẢ LẠI | GIÁ | ... | THÀNH TIỀN BÁN | THÀNH TIỀN NTL | MÔ TẢ | HẠNG KHÁCH | CHƯƠNG TRÌNH KHUYẾN MẠI | SubClass1 | THUỘC TÍNH 1 | NĂM SX | MÃ HÀNG1 | NHÂN VIÊN | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000175 | 1160637 | I7JCK601F-015 | 0 | 1 | 1290000 | ... | 0.0 | 387000.0 | 0 | AppMember | 0 | cổ 5cm | 3 lớp | Đông 2019 | I7JCK601F | 0 |
| 1 | 2 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000176 | 907256 | I9COA502H-005 | 0 | 2 | 790000 | ... | 0.0 | 474000.0 | 0 | AppMember | 0 | có mũ | 2 lớp mỏng | Đông 2020 | I9COA502H | 0 |
| 2 | 3 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000177 | 163424 | I7SWT601F-001 | 0 | 1 | 490000 | ... | 0.0 | 147000.0 | 0 | AppMember | 0 | cổ tròn | Len | Đông 2019 | I7SWT601F | 0 |
| 3 | 4 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000178 | 1834386 | M9ACP500H-002 | 0 | 1 | 150000 | ... | 0.0 | 45000.0 | 0 | AppMember | 0 | 0 | 0 | Đông 2020 | M9ACP500H | 0 |
| 4 | 5 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000179 | 1984934 | C9SML008D-002 | 0 | 1 | 290000 | ... | 0.0 | 87000.0 | 0 | AppMember | 0 | 0 | 0 | Đông 2018 | C9SML-008D | 0 |
| 5 | 6 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000180 | 1594687 | I9SWS503H-007 | 0 | 1 | 250000 | ... | 0.0 | 75000.0 | 0 | AppMember | 0 | cổ tròn | 0 | Đông 2020 | I9SWS503H | 0 |
| 6 | 7 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000181 | 1831070 | E7SHO262H-009 | 0 | 1 | 490000 | ... | 0.0 | 343000.0 | 0 | AppMember | 0 | 0 | êm chân | 2021 | E7SHO262H | 0 |
| 7 | 8 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000182 | 1651202 | I5JOG501H-009 | 0 | 1 | 190000 | ... | 0.0 | 57000.0 | 0 | AppMember | 0 | 0 | 0 | Đông 2020 | I5JOG501H | 0 |
| 8 | 9 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000182 | 1651202 | I9JOG501H-013 | 0 | 1 | 350000 | ... | 0.0 | 105000.0 | 0 | AppMember | 0 | 0 | Si chun | Đông 2020 | I9JOG501H | 0 |
| 9 | 10 | 141 | TOKYOLIFE Tam Điệp | 2021-01-31 | NTL_141/21-000183 | 1998294 | I7PAN500H-005 | 0 | 1 | 350000 | ... | 0.0 | 105000.0 | 0 | AppMember | 0 | 0 | Si chun | Đông 2020 | I7PAN500H | 0 |
10 rows × 22 columns
sql_query = """
SELECT hanghoa.[MÃ HÀNG],[TÊN HÀNG],[GIỚI TÍNH],[NHÓM HÀNG],[DÒNG HÀNG],[KẾT CẤU],[NGÀY HĐ],[SỐ HĐ],[SL BÁN],[SL TRẢ LẠI],[THÀNH TIỀN BÁN]
FROM hanghoa JOIN hoadon
ON hanghoa.[MÃ HÀNG] = hoadon.[MÃ HÀNG]
"""
df_EDA = pd.read_sql(sql_query, conn)
df_EDA
| MÃ HÀNG | TÊN HÀNG | GIỚI TÍNH | NHÓM HÀNG | DÒNG HÀNG | KẾT CẤU | NGÀY HĐ | SỐ HĐ | SL BÁN | SL TRẢ LẠI | THÀNH TIỀN BÁN | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | I7JCK601F-015 | Áo khoác lông vũ Nam 3 lớp cổ 5cm dáng ngắn I7... | Nam | Thời trang BASIC | Khoác ngoài | Áo khoác lông vũ | 2021-01-31 | NTL_141/21-000175 | 0 | 1 | 0.0 |
| 1 | I9COA502H-005 | Áo khoác Nữ dáng dài I9COA502H | Nữ | Thời trang BASIC | Phần trên | Áo khoác | 2021-01-31 | NTL_141/21-000176 | 0 | 2 | 0.0 |
| 2 | I7SWT601F-001 | Áo len Nam cổ tròn I7SWT601F | Nam | Thời trang BASIC | Len sợi | Áo len | 2021-01-31 | NTL_141/21-000177 | 0 | 1 | 0.0 |
| 3 | M9ACP500H-002 | Quần Leggings lửng Nữ M9ACP500H | Nữ | Thời trang BASIC | Đồ tập | Quần Leggings | 2021-01-31 | NTL_141/21-000178 | 0 | 1 | 0.0 |
| 4 | C9SML008D-002 | Quần Leggings Nữ C9SML-008D | Nữ | Thời trang BASIC | Phần dưới | Quần Leggings | 2021-01-31 | NTL_141/21-000179 | 0 | 1 | 0.0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 115045 | G9SMT007J-002 | Áo giữ nhiệt WM Original Nữ cổ lọ G9SMT007J | Nữ | Thời trang SMART | Warmmax | Áo giữ nhiệt | 2021-12-01 | XBL_141/21-015685 | 2 | 0 | 318000.0 |
| 115046 | E7JEA001H-001 | Quần Jeans Nam E7JEA001H | Nam | Thời trang NOW | Phần dưới | Quần Jeans | 2021-12-01 | XBL_141/21-015686 | 2 | 0 | 590000.0 |
| 115047 | N7BBE005J-002 | Áo Bomber Nam N7BBE005J | Nam | Thời trang NOW | Khoác ngoài | Áo Bomber | 2021-12-01 | XBL_141/21-015687 | 2 | 0 | 1666000.0 |
| 115048 | N7SWS014J-010 | Áo nỉ chui đầu Nam cổ tròn N7SWS014J | Nam | Thời trang NOW | Phần trên | Áo nỉ chui đầu | 2021-12-01 | XBL_141/21-015687 | 2 | 0 | 966000.0 |
| 115049 | I9TSH602J-005 | Áo T-shirt Nữ cổ tròn I9TSH602J | Nữ | Thời trang BASIC | Phần trên | Áo T-Shirt | 2021-12-01 | XBL_141/21-015688 | 2 | 0 | 158000.0 |
115050 rows × 11 columns
check = ['Túi bán hàng']
df_EDA = df_EDA[~df_EDA['NHÓM HÀNG'].isin(check)]
df_EDA['Month'] = df_EDA['NGÀY HĐ'].dt.month
df_EDA['Year'] = df_EDA['NGÀY HĐ'].dt.year
df_EDA['Day'] = df_EDA['NGÀY HĐ'].dt.day
df_EDA
| MÃ HÀNG | TÊN HÀNG | GIỚI TÍNH | NHÓM HÀNG | DÒNG HÀNG | KẾT CẤU | NGÀY HĐ | SỐ HĐ | SL BÁN | SL TRẢ LẠI | THÀNH TIỀN BÁN | Month | Year | Day | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | I7JCK601F-015 | Áo khoác lông vũ Nam 3 lớp cổ 5cm dáng ngắn I7... | Nam | Thời trang BASIC | Khoác ngoài | Áo khoác lông vũ | 2021-01-31 | NTL_141/21-000175 | 0 | 1 | 0.0 | 1 | 2021 | 31 |
| 1 | I9COA502H-005 | Áo khoác Nữ dáng dài I9COA502H | Nữ | Thời trang BASIC | Phần trên | Áo khoác | 2021-01-31 | NTL_141/21-000176 | 0 | 2 | 0.0 | 1 | 2021 | 31 |
| 2 | I7SWT601F-001 | Áo len Nam cổ tròn I7SWT601F | Nam | Thời trang BASIC | Len sợi | Áo len | 2021-01-31 | NTL_141/21-000177 | 0 | 1 | 0.0 | 1 | 2021 | 31 |
| 3 | M9ACP500H-002 | Quần Leggings lửng Nữ M9ACP500H | Nữ | Thời trang BASIC | Đồ tập | Quần Leggings | 2021-01-31 | NTL_141/21-000178 | 0 | 1 | 0.0 | 1 | 2021 | 31 |
| 4 | C9SML008D-002 | Quần Leggings Nữ C9SML-008D | Nữ | Thời trang BASIC | Phần dưới | Quần Leggings | 2021-01-31 | NTL_141/21-000179 | 0 | 1 | 0.0 | 1 | 2021 | 31 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 115045 | G9SMT007J-002 | Áo giữ nhiệt WM Original Nữ cổ lọ G9SMT007J | Nữ | Thời trang SMART | Warmmax | Áo giữ nhiệt | 2021-12-01 | XBL_141/21-015685 | 2 | 0 | 318000.0 | 12 | 2021 | 1 |
| 115046 | E7JEA001H-001 | Quần Jeans Nam E7JEA001H | Nam | Thời trang NOW | Phần dưới | Quần Jeans | 2021-12-01 | XBL_141/21-015686 | 2 | 0 | 590000.0 | 12 | 2021 | 1 |
| 115047 | N7BBE005J-002 | Áo Bomber Nam N7BBE005J | Nam | Thời trang NOW | Khoác ngoài | Áo Bomber | 2021-12-01 | XBL_141/21-015687 | 2 | 0 | 1666000.0 | 12 | 2021 | 1 |
| 115048 | N7SWS014J-010 | Áo nỉ chui đầu Nam cổ tròn N7SWS014J | Nam | Thời trang NOW | Phần trên | Áo nỉ chui đầu | 2021-12-01 | XBL_141/21-015687 | 2 | 0 | 966000.0 | 12 | 2021 | 1 |
| 115049 | I9TSH602J-005 | Áo T-shirt Nữ cổ tròn I9TSH602J | Nữ | Thời trang BASIC | Phần trên | Áo T-Shirt | 2021-12-01 | XBL_141/21-015688 | 2 | 0 | 158000.0 | 12 | 2021 | 1 |
110722 rows × 14 columns
app = JupyterDash(__name__)
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
options=[2020,2021,2022],
value=2022,
id='Year-check'
)],style={'width': '48%','float': 'right', 'display': 'block'}),
html.Div([
dcc.Dropdown(
options=[1,2,3,4,5,6,7,8,9,10,11,12],
value=1,
id='Month-slider'
)],style={'width': '48%', 'display': 'block'}),
]),
dcc.Graph(id='graph-with-slider'),
])
@app.callback(
Output('graph-with-slider', 'figure'),
Input('Month-slider', 'value'),
Input('Year-check', 'value'))
def update_figure(selected_month,Year_check):
df_gioitinh = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='GIỚI TÍNH')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False)
df_nhomhang = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='NHÓM HÀNG')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False).head(5)
df_ketcau = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='KẾT CẤU')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False).head(10)
df_doanhthu = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='NGÀY HĐ')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False)
fig = make_subplots(rows=2, cols=2,specs=[[{"type": "pie"}, {"type": "pie"}],[{"type": "bar"},{"type": "bar"}]],vertical_spacing = 0.15,subplot_titles=("Tỉ trọng giới tính","Tỉ trọng kết cấu", "Top kết cấu",'Doanh thu'))
fig.add_trace(go.Pie(values=df_gioitinh.values,labels=df_gioitinh.index),row=1, col=1)
fig.add_trace(go.Pie(values=df_nhomhang.values,labels=df_nhomhang.index),row=1, col=2)
fig.add_trace(go.Bar(y=df_ketcau.values,x=df_ketcau.index),row=2, col=1)
fig.add_trace(go.Bar(y=df_doanhthu.values,x=df_doanhthu.index),row=2, col=2)
fig.update_layout(width=950, height=600)
#fig.update_layout(paper_bgcolor="#cdbda3")
fig.update_xaxes(showticklabels=False)
fig.update(layout_showlegend=False)
return fig
if __name__ == '__main__':
app.run_server(mode='inline')
app = JupyterDash(__name__)
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
options=[i for i in range(1,32)],
value=5,
id='Day-check'
)],style={'width': '34%','float': 'left', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
options=[2020,2021,2022],
value=2022,
id='Year-check'
)],style={'width': '34%','float': 'right', 'display': 'inline-block'}),
html.Div([
dcc.Dropdown(
options=[1,2,3,4,5,6,7,8,9,10,11,12],
value=5,
id='Month-slider'
)],style={'width': '32%', 'display': 'inline-block'}),
]),
dcc.Graph(id='graph-with-slider'),
])
@app.callback(
Output('graph-with-slider', 'figure'),
Input('Day-check', 'value'),
Input('Month-slider', 'value'),
Input('Year-check', 'value'))
def update_figure(Day_check,selected_month,Year_check):
# Xử lý tạo tabel doanh thu top kết cấu
s_today = df_EDA[(df_EDA.Day == Day_check)&(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='KẾT CẤU')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False).head(10)
s_yesday = df_EDA[(df_EDA.Day == (Day_check-1))&(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='KẾT CẤU')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False).head(10)
s_monthday = df_EDA[(df_EDA.Day == Day_check)&(df_EDA.Month == (selected_month-1))&(df_EDA.Year == Year_check)].groupby(by='KẾT CẤU')['THÀNH TIỀN BÁN'].sum().sort_values(ascending=False).head(10)
s_kc = pd.concat([s_today,s_yesday,s_monthday],axis=1).head(10)
s_kc['Kết cấu'] = s_kc.index
s_kc.columns = ['Hôm nay','Hôm qua','Tháng trước','Kết cấu']
fig = go.Figure(data =[go.Table(header=dict(values=['Kết cấu','Hôm nay','Hôm qua','Tháng trước'],
fill_color='paleturquoise',
align='left'),
cells=dict(values=[s_kc['Kết cấu'],s_kc['Hôm nay'],s_kc['Hôm qua'],s_kc['Tháng trước']],
fill_color='lavender',
align='left'))])
fig.update_layout(width=950, height=600)
fig.update_xaxes(showticklabels=False)
fig.update(layout_showlegend=False)
return fig
if __name__ == '__main__':
app.run_server(mode='inline')
app = JupyterDash(__name__)
app.layout = html.Div([
html.Div([
html.Div([
dcc.Dropdown(
options=[2020,2021,2022],
value=2022,
id='Year-check'
)],style={'width': '48%','float': 'right', 'display': 'block'}),
html.Div([
dcc.Dropdown(
options=[1,2,3,4,5,6,7,8,9,10,11,12],
value=6,
id='Month-slider'
)],style={'width': '48%', 'display': 'block'}),
]),
dcc.Graph(id='graph-with-slider'),
])
@app.callback(
Output('graph-with-slider', 'figure'),
Input('Month-slider', 'value'),
Input('Year-check', 'value'))
def update_figure(selected_month,Year_check):
df_ketcau = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == Year_check)].groupby(by='NGÀY HĐ')['THÀNH TIỀN BÁN'].sum().head(10)
df_ketcau = df_ketcau.sort_index(ascending=True)
df_lastketcau = df_EDA[(df_EDA.Month == selected_month)&(df_EDA.Year == (Year_check-1))].groupby(by='NGÀY HĐ')['THÀNH TIỀN BÁN'].sum()
df_lastketcau = df_lastketcau.sort_index(ascending=True)
fig = px.line(df_ketcau,x=df_ketcau.index,y=df_ketcau.values)
fig.add_scatter(x=df_ketcau.index,y=df_lastketcau.values,name = 'Last')
fig.update_layout(width=950, height=600)
#fig.update_layout(paper_bgcolor="#cdbda3")
#fig.update_xaxes(showticklabels=False)
fig.update(layout_showlegend=True)
return fig
if __name__ == '__main__':
app.run_server(mode='inline')
sql_query = """
SELECT *
FROM hoadon
Where [NGÀY HĐ]>= DATEADD(year, -1,GETDATE())
"""
df_CUS = pd.read_sql(sql_query, conn)
df_CUS
| STT_ID | MÃ CN | CHI NHÁNH | NGÀY HĐ | SỐ HĐ | MÃ KHÁCH 2 | MÃ HÀNG | SL BÁN | SL TRẢ LẠI | GIÁ | ... | THÀNH TIỀN BÁN | THÀNH TIỀN NTL | MÔ TẢ | HẠNG KHÁCH | CHƯƠNG TRÌNH KHUYẾN MẠI | SubClass1 | THUỘC TÍNH 1 | NĂM SX | MÃ HÀNG1 | NHÂN VIÊN | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 8224 | 141 | TOKYOLIFE Tam Điệp | 2022-01-31 | NTL_141/22-000192 | 1622305 | H2I7FLJ501H01 | 0 | 1 | 390000 | ... | 0.0 | 219000.0 | 0 | AppMember | 0 | cổ lọ | lông cừu nhân tạo | Đông 2020 | H2/I7FLJ501H | 0 |
| 1 | 8225 | 141 | TOKYOLIFE Tam Điệp | 2022-01-31 | NTL_141/22-000193 | 2239595 | M9SHO223I-012 | 0 | 1 | 890000 | ... | 0.0 | 623000.0 | 0 | AppMember | 0 | 0 | kháng khuẩn | 2021 | M9SHO223I | 0 |
| 2 | 8226 | 141 | TOKYOLIFE Tam Điệp | 2022-01-31 | NTL_141/22-000194 | 2639452 | I7FEJ005J-010 | 0 | 1 | 890000 | ... | 0.0 | 598996.7 | 0 | Khách Lẻ | 0 | Cổ cao | 2 lớp siêu nhẹ | Đông 2021 | I7FEJ005J | 0 |
| 3 | 8227 | 141 | TOKYOLIFE Tam Điệp | 2022-01-31 | NTL_141/22-000195 | 2288075 | N3SLI017I-022 | 0 | 1 | 120000 | ... | 0.0 | 89000.4 | 0 | AppMember | 0 | êm chân | siêu nhẹ | 2021 | N3SLI017I | 0 |
| 4 | 8228 | 141 | TOKYOLIFE Tam Điệp | 2022-01-31 | XBL_141/22-003060 | 1598604 | E7GLV038H-001 | 2 | 0 | 120000 | ... | 144000.0 | 0.0 | 0 | Khách Lẻ | LGB/22-000019 | 0 | 0 | 2021 | E7GLV038H | 0 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 47355 | 115046 | 141 | TOKYOLIFE Tam Điệp | 2021-12-01 | XBL_141/21-015685 | 2391030 | G9SMT007J-002 | 2 | 0 | 490000 | ... | 318000.0 | 0.0 | 0 | AppMember | LGB/21-000123 | cổ lọ | WM Original | Đông 2021 | G9SMT007J | 0 |
| 47356 | 115047 | 141 | TOKYOLIFE Tam Điệp | 2021-12-01 | XBL_141/21-015686 | 1960546 | E7JEA001H-001 | 2 | 0 | 590000 | ... | 590000.0 | 0.0 | 0 | AppMember | LGB/21-000124 | 0 | Jean | Đông 2020 | E7JEA001H | 0 |
| 47357 | 115048 | 141 | TOKYOLIFE Tam Điệp | 2021-12-01 | XBL_141/21-015687 | 1960546 | N7BBE005J-002 | 2 | 0 | 1190000 | ... | 1666000.0 | 0.0 | 0 | AppMember | LGB/21-000124 | 0 | 2 lớp | Đông 2021 | N7BBE005J | 0 |
| 47358 | 115049 | 141 | TOKYOLIFE Tam Điệp | 2021-12-01 | XBL_141/21-015687 | 1960546 | N7SWS014J-010 | 2 | 0 | 690000 | ... | 966000.0 | 0.0 | 0 | AppMember | LGB/21-000124 | cổ tròn | 0 | Đông 2021 | N7SWS014J | 0 |
| 47359 | 115050 | 141 | TOKYOLIFE Tam Điệp | 2021-12-01 | XBL_141/21-015688 | 1677251 | I9TSH602J-005 | 2 | 0 | 250000 | ... | 158000.0 | 0.0 | 0 | AppMember | LGB/21-000124 | cổ tròn | 0 | Đông 2021 | I9TSH602J | 0 |
47360 rows × 22 columns
sql_query = """
SELECT hoadon.[MÃ KHÁCH 2],khachhang.[TÊN KHÁCH],MAX([NGÀY HĐ]) AS 'LAST BUY',COUNT(DISTINCT [SỐ HĐ]) AS 'FREQUENCY',SUM ([THÀNH TIỀN BÁN]) AS 'MONETARY'
FROM hoadon JOIN khachhang
ON hoadon.[MÃ KHÁCH 2] = khachhang.[MÃ KHÁCH 2]
Where [NGÀY HĐ]>= DATEADD(year, -1,GETDATE())
GROUP BY hoadon.[MÃ KHÁCH 2],khachhang.[TÊN KHÁCH]
"""
df_RFM = pd.read_sql(sql_query, conn)
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | |
|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 |
| ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 |
6088 rows × 5 columns
df_RFM['RECENCY'] = pd.to_datetime("today") - df_RFM['LAST BUY']
df_RFM['RECENCY'] = df_RFM['RECENCY'].dt.days
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | |
|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 |
| ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 |
6088 rows × 6 columns
df_RFM.sort_values(by='FREQUENCY',ascending=False).head(10)
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | |
|---|---|---|---|---|---|---|
| 1386 | 1598604 | TL TDIE_Khách không cho thông tin | 2022-06-17 | 592 | 248854000.0 | 31 |
| 2625 | 1956765 | Nguyễn Ngọc Bảo Uyên | 2022-04-27 | 105 | 33644000.0 | 82 |
| 1161 | 1567064 | NV_Ngô Thị Dần | 2022-06-16 | 81 | 35820960.0 | 32 |
| 13 | 134926 | Khách nươc ngoài | 2022-06-16 | 69 | 38176200.0 | 32 |
| 2560 | 1924581 | Ms Phương | 2022-06-05 | 68 | 25952000.0 | 43 |
| 1734 | 1655704 | Anh Thoan | 2022-06-07 | 59 | 25632000.0 | 41 |
| 1158 | 1565374 | NV_Vũ Thùy Trang | 2022-06-09 | 54 | 14210000.0 | 39 |
| 1323 | 1594230 | Ms.phương | 2022-06-07 | 52 | 40911200.0 | 41 |
| 1160 | 1567053 | NV_Phạm Thị Lan | 2022-06-16 | 50 | 21382600.0 | 32 |
| 1170 | 1573533 | NV_Đinh Thị Thùy | 2022-05-16 | 42 | 12545200.0 | 63 |
msk = df_RFM['TÊN KHÁCH'].str.contains('(NV_)[A-Za-z]{0}')
df_RFM[msk]
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | |
|---|---|---|---|---|---|---|
| 1013 | 1372679 | NV_Lê Thị Lành | 2021-11-23 | 3 | 1220000.0 | 237 |
| 1026 | 1390692 | NV_Nguyễn Nhân Tâm | 2021-11-22 | 1 | 590000.0 | 238 |
| 1157 | 1565114 | NV_Phạm Thị Hằng | 2021-07-25 | 1 | 130000.0 | 358 |
| 1158 | 1565374 | NV_Vũ Thùy Trang | 2022-06-09 | 54 | 14210000.0 | 39 |
| 1160 | 1567053 | NV_Phạm Thị Lan | 2022-06-16 | 50 | 21382600.0 | 32 |
| 1161 | 1567064 | NV_Ngô Thị Dần | 2022-06-16 | 81 | 35820960.0 | 32 |
| 1170 | 1573533 | NV_Đinh Thị Thùy | 2022-05-16 | 42 | 12545200.0 | 63 |
| 1846 | 1685398 | NV_Đỗ Thị Mỹ Hằng | 2021-11-23 | 3 | 350000.0 | 237 |
| 2563 | 1926395 | NV_Đinh Thị Thu Hà | 2021-10-24 | 1 | 240000.0 | 267 |
| 2905 | 2090698 | NV_Lại Thị Thùy Linh | 2022-05-01 | 9 | 1934000.0 | 78 |
df_RFM = df_RFM[~msk &(df_RFM['TÊN KHÁCH']!='TL TDIE_Khách không cho thông tin')&(df_RFM['TÊN KHÁCH']!='Khách nươc ngoài')]
px.histogram(df_RFM[df_RFM['FREQUENCY']<10],x='FREQUENCY')
labels = [1,2,3]
values = [df_RFM[df_RFM['FREQUENCY']<2]['FREQUENCY'].count(),df_RFM[(df_RFM['FREQUENCY']<5)&(df_RFM['FREQUENCY']>1)]['FREQUENCY'].count(),df_RFM[df_RFM['FREQUENCY']>4]['FREQUENCY'].count()]
fig = px.pie(values=values,names=labels)
fig.show()
df_RFM['CL_FREQUENCY'] = df_RFM['FREQUENCY'].apply(lambda x: 1 if x < 2 else (2 if x > 1 and x < 5 else 3))
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | CL_FREQUENCY | |
|---|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 | 2 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 | 1 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 | 1 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 | 1 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 | 3 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 | 1 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 | 2 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 | 1 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 | 1 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 | 1 |
6076 rows × 7 columns
px.histogram(df_RFM[df_RFM['MONETARY']<10000000],x='MONETARY')
labels = [1,2,3]
values = [df_RFM[df_RFM['MONETARY']<1200000]['MONETARY'].count(),df_RFM[(df_RFM['MONETARY']<3000000)&(df_RFM['MONETARY']>1200000)]['MONETARY'].count(),df_RFM[df_RFM['MONETARY']>3000000]['MONETARY'].count()]
fig = px.pie(values=values,names=labels)
fig.show()
df_RFM['CL_MONETARY'] = df_RFM['MONETARY'].apply(lambda x: 1 if x < 1200000 else (2 if x > 1199000 and x < 3000000 else 3))
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | CL_FREQUENCY | CL_MONETARY | |
|---|---|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 | 2 | 1 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 | 1 | 2 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 | 1 | 1 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 | 1 | 3 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 | 3 | 3 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 | 1 | 1 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 | 2 | 2 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 | 1 | 1 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 | 1 | 1 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 | 1 | 2 |
6076 rows × 8 columns
px.histogram(df_RFM['RECENCY'],x='RECENCY')
labels = [1,2,3]
values = [df_RFM[df_RFM['RECENCY']<160]['RECENCY'].count(),df_RFM[(df_RFM['RECENCY']<240)&(df_RFM['RECENCY']>160)]['RECENCY'].count(),df_RFM[df_RFM['RECENCY']>240]['RECENCY'].count()]
fig = px.pie(values=values,names=labels)
fig.show()
df_RFM['CL_RECENCY'] = df_RFM['RECENCY'].apply(lambda x: 1 if x < 160 else (2 if x > 159 and x < 2400 else 3))
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | CL_FREQUENCY | CL_MONETARY | CL_RECENCY | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 | 2 | 1 | 1 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 | 1 | 2 | 2 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 | 1 | 1 | 1 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 | 1 | 3 | 2 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 | 3 | 3 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 | 1 | 1 | 1 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 | 2 | 2 | 1 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 | 1 | 1 | 1 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 | 1 | 1 | 1 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 | 1 | 2 | 1 |
6076 rows × 9 columns
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | CL_FREQUENCY | CL_MONETARY | CL_RECENCY | |
|---|---|---|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 | 2 | 1 | 1 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 | 1 | 2 | 2 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 | 1 | 1 | 1 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 | 1 | 3 | 2 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 | 3 | 3 | 1 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 | 1 | 1 | 1 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 | 2 | 2 | 1 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 | 1 | 1 | 1 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 | 1 | 1 | 1 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 | 1 | 2 | 1 |
6076 rows × 9 columns
from sklearn.preprocessing import StandardScaler
X = df_RFM[['FREQUENCY','MONETARY','RECENCY']].values[:,:]
Clus_dataSet = StandardScaler().fit_transform(X)
pd.DataFrame(Clus_dataSet).head()
| 0 | 1 | 2 | |
|---|---|---|---|
| 0 | -0.202661 | -0.376700 | -0.760288 |
| 1 | -0.471988 | 0.074970 | 2.215395 |
| 2 | -0.471988 | -0.370093 | -0.478639 |
| 3 | -0.471988 | 0.360268 | 0.060168 |
| 4 | 1.143978 | 0.473786 | -1.127656 |
# Chọn số cụm bằng Elbow
import seaborn as sns
from sklearn.cluster import KMeans
sse = {}
for k in range (1,27):
k_means = KMeans(init = "k-means++", n_clusters = k, n_init = 12)
k_means.fit(Clus_dataSet)
sse[k] = k_means.inertia_
plt.xlabel('k')
plt.ylabel('sse')
sns.pointplot(x=list(sse.keys()),y=list(sse.values()))
plt.show()
model = KMeans(init = "k-means++", n_clusters = 9, n_init = 12)
model.fit(Clus_dataSet)
KMeans(n_clusters=9, n_init=12)
df_RFM['Label'] = model.labels_
df_RFM
| MÃ KHÁCH 2 | TÊN KHÁCH | LAST BUY | FREQUENCY | MONETARY | RECENCY | CL_FREQUENCY | CL_MONETARY | CL_RECENCY | Label | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 126781 | Phạm Nhật Lệ | 2022-04-08 | 2 | 990000.0 | 101 | 2 | 1 | 1 | 5 |
| 1 | 127020 | Chị Lê Diệu Linh | 2021-08-08 | 1 | 2494000.0 | 344 | 1 | 2 | 2 | 8 |
| 2 | 127463 | Nv Đỗ Thị Thu Trang | 2022-03-16 | 1 | 1012000.0 | 124 | 1 | 1 | 1 | 1 |
| 3 | 128098 | Phạm Thanh Thủy | 2022-01-31 | 1 | 3444000.0 | 168 | 1 | 3 | 2 | 1 |
| 4 | 128174 | Lê Thị Huế | 2022-05-08 | 7 | 3822000.0 | 71 | 3 | 3 | 1 | 2 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6083 | 2822366 | Phuong Pham | 2022-06-16 | 1 | 744000.0 | 32 | 1 | 1 | 1 | 5 |
| 6084 | 2822527 | Anh Tưởng | 2022-06-16 | 3 | 2810000.0 | 32 | 2 | 2 | 1 | 5 |
| 6085 | 2822614 | Anh Linh | 2022-06-16 | 1 | 630000.0 | 32 | 1 | 1 | 1 | 5 |
| 6086 | 2822693 | Thu Hà | 2022-06-16 | 1 | 928000.0 | 32 | 1 | 1 | 1 | 5 |
| 6087 | 2823376 | Anh Hội | 2022-06-17 | 1 | 1336000.0 | 31 | 1 | 2 | 1 | 5 |
6076 rows × 10 columns
df_RFM.groupby('Label').agg(
{
'MONETARY':'mean',
'FREQUENCY':'mean',
'RECENCY':'mean'
}
).round(2)
| MONETARY | FREQUENCY | RECENCY | |
|---|---|---|---|
| Label | |||
| 0 | 3776010.25 | 4.10 | 171.94 |
| 1 | 930922.71 | 1.42 | 157.01 |
| 2 | 5946333.47 | 7.16 | 77.05 |
| 3 | 982696.08 | 1.41 | 222.24 |
| 4 | 27755279.93 | 24.33 | 57.57 |
| 5 | 1549752.91 | 1.97 | 69.81 |
| 6 | 31534800.00 | 71.00 | 51.75 |
| 7 | 12756632.32 | 13.20 | 79.87 |
| 8 | 927447.96 | 1.38 | 311.83 |
# Nguồn tham khảo
#https://docs.microsoft.com/en-us/sql/machine-learning/data-exploration/python-dataframe-pandas?view=sql-server-ver16
#https://github.com/mkleehammer/pyodbc/wiki/Getting-started
#https://medium.com/plotly/introducing-jupyterdash-811f1f57c02e